package com.blobfish.fiction.common;

import com.blobfish.fiction.blog.BlogController;
import com.blobfish.fiction.book.BookController;
import com.blobfish.fiction.common.base.interceptor.AuthInterceptor;
import com.blobfish.fiction.common.base.interceptor.ErrorInterceptor;
import com.blobfish.fiction.common.plugin.FunctionDownloadPlugin;
import com.blobfish.fiction.common.plugin.ShowcaseWebsocketPlugin;
import com.blobfish.fiction.common.tio.websocket.ShowcaseServerConfig;
import com.blobfish.fiction.common.tio.websocket.ShowcaseWsMsgHandler;
import com.blobfish.fiction.common.util.DownloadUtil;
import com.blobfish.fiction.index.IndexController;
import com.blobfish.fiction.common.model._MappingKit;
import com.blobfish.fiction.message.MessageController;
import com.blobfish.fiction.user.LoginController;
import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.JFinalConfig;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;
import com.jfinal.core.JFinal;
import com.jfinal.ext.handler.ContextPathHandler;
import com.jfinal.kit.PropKit;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.cron4j.Cron4jPlugin;
import com.jfinal.plugin.druid.DruidPlugin;
import com.jfinal.plugin.redis.Redis;
import com.jfinal.plugin.redis.RedisPlugin;
import com.jfinal.template.Engine;
import com.jfinal.template.source.ClassPathSourceFactory;

/**
 * 本 demo 仅表达最为粗浅的 jfinal 用法，更为有价值的实用的企业级用法
 * 详见 JFinal 俱乐部: http://jfinal.com/club
 * <p>
 * API引导式配置
 */
public class DemoConfig extends JFinalConfig {
    private static final Log log = Log.getLog(DemoConfig.class);
    /**
     * 启动入口，运行此 main 方法可以启动项目，此 main 方法可以放置在任意的 Class 类定义中，不一定要放于此
     * <p>
     * 使用本方法启动过第一次以后，会在开发工具的 debug、run configuration 中自动生成
     * 一条启动配置项，可对该自动生成的配置再继续添加更多的配置项，例如 Program arguments
     * 可配置为：src/main/webapp 80 / 5
     */
    public static void main(String[] args) {
        JFinal.start("src/main/webapp", 80, "/", 5);
    }

    /**
     * 配置常量
     */
    public void configConstant(Constants me) {
        // 加载少量必要配置，随后可用PropKit.get(...)获取值
        PropKit.use("a_little_config.txt");
        me.setDevMode(PropKit.getBoolean("devMode", false));

        // 支持 Controller、Interceptor 之中使用 @Inject 注入业务层，并且自动实现 AOP
        me.setInjectDependency(true);
    }

    /**
     * 配置路由
     * @param me 配置实体
     */
    @Override
    public void configRoute(Routes me) {
        me.setBaseViewPath("/page");
        // 第三个参数为该Controller的视图存放路径
        me.add("/", IndexController.class, "/index");
        // 第三个参数省略时默认与第一个参数值相同，在此即为 "/blog"
        me.add("/blog", BlogController.class);
        me.add("/book", BookController.class);
        me.add("/login", LoginController.class);
        me.add("/message", MessageController.class);
    }

    public void configEngine(Engine me) {
        // me.addSharedFunction("/common/_layout.html");
        // me.addSharedFunction("/common/_paginate.html");
    }

    /**
     * 配置插件
     */
    public void configPlugin(Plugins me) {
        // 配置 druid 数据库连接池插件
        DruidPlugin druidPlugin = new DruidPlugin(PropKit.get("jdbcUrl"), PropKit.get("user"), PropKit.get("password").trim());
        me.add(druidPlugin);

        // 配置ActiveRecord插件
        ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin);
        arp.getEngine().setSourceFactory(new ClassPathSourceFactory());
        arp.addSqlTemplate("sql/all.sql");
        arp.getEngine().setDevMode(true);
        // 所有映射在 MappingKit 中自动化搞定
        _MappingKit.mapping(arp);
        me.add(arp);

        // 配置下载插件
        me.add(new FunctionDownloadPlugin());

        // 配置Redis插件
        RedisPlugin masterRedis = new RedisPlugin("master", PropKit.get("redisUrl"), PropKit.get("redisPwd"));
        me.add(masterRedis);

        // 添加定时任务
        Cron4jPlugin cp = new Cron4jPlugin("cron.txt");
        me.add(cp);

        // 推送服务plugin
        try {
            ShowcaseWebsocketPlugin showcaseWebsocketPlugin = new ShowcaseWebsocketPlugin(ShowcaseServerConfig.SERVER_PORT, ShowcaseWsMsgHandler.me);
            me.add(showcaseWebsocketPlugin);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    public static DruidPlugin createDruidPlugin() {
        return new DruidPlugin(PropKit.get("jdbcUrl"), PropKit.get("user"), PropKit.get("password").trim());
    }

    /**
     * 配置全局拦截器
     */
    public void configInterceptor(Interceptors me) {
        // 异常处理拦截器
        me.add(new ErrorInterceptor());
        // 权限拦截器
        me.add(new AuthInterceptor());
    }

    /**
     * 配置处理器
     */
    public void configHandler(Handlers me) {
        me.add(new ContextPathHandler());
    }

    @Override
    public void afterJFinalStart() {
        super.afterJFinalStart();
        // 清空自动检测下载失败任务列表
        Redis.use("master").del(PropKit.get("cacheName.DOWNLOADED_BOOK_NO"));
        Redis.use("master").del(PropKit.get("cacheName.UNDOWNLOAD_BOOK_NO"));
        // 开始下载因意外重启导致未完成的数据
        DownloadUtil.getInstance().startBreakpointDownload();
        // 加载不需要权限验证的url
        Redis.use("master").sadd(PropKit.get("cacheName.AUTH_ANON_URL"), PropKit.get("auth.anon.url").split(PropKit.get("replaceRegSep")));
    }

    @Override
    public void beforeJFinalStop() {
        super.beforeJFinalStop();
        // 清空自动检测下载失败任务列表
        Redis.use("master").del(PropKit.get("cacheName.DOWNLOADED_BOOK_NO"));
        Redis.use("master").del(PropKit.get("cacheName.UNDOWNLOAD_BOOK_NO"));
        Redis.use("master").del(PropKit.get("cacheName.UNDOWNLOAD_BOOK_NO"));
    }
}
